﻿using Microsoft.AspNetCore.Authorization.Policy;
using Microsoft.AspNetCore.Authorization;
using System.IdentityModel.Tokens.Jwt;

namespace AbpWebapi
{
    public class CustomAuthorizationMiddleware : IAuthorizationMiddlewareResultHandler
    {
        public async Task HandleAsync(RequestDelegate next, HttpContext context, AuthorizationPolicy policy, PolicyAuthorizationResult authorizeResult)
        {
            if (authorizeResult.Succeeded == false)
            {
                var authHeaderVal = context.Request.Headers["Authorization"];// 从请求头中获取Authorization字段的值，该值应为JWT Token
                if (authHeaderVal.Count > 0)
                {
                    var tokenVal = authHeaderVal.ToString().Split(" ")[1];// 将JWT Token字符串分割成数组，取得第二个元素（即Token字符串本身）
                    var tokenHandler = new JwtSecurityTokenHandler();// 使用JwtSecurityTokenHandler类处理Token字符串
                    var token = tokenHandler.ReadJwtToken(tokenVal);     // 将Token字符串转换成JwtSecurityToken类型的对象

                    var expClaim = token.Claims.FirstOrDefault(c => c.Type == JwtRegisteredClaimNames.Exp);// 从Token中获取到期时间的Claims属性（Claim就是关于Token的一个声明）
                    if (expClaim != null)// 如果存在到期时间的Claims属性
                    {
                        var expVal = long.Parse(expClaim.Value); // 从Claims属性中取出到期时间值，并将其转换成DateTime类型
                        var expDate = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(expVal);
                        if (expDate < DateTime.UtcNow) // 如果到期时间早于当前时间，说明Token已过期
                        {
                            await context.Response.WriteAsJsonAsync(new { Code = 401, Message = "Token已过期,请重新登录" });
                            return;
                        }
                    }

                }

                if (context.User.Identity.IsAuthenticated == false)
                {
                    await context.Response.WriteAsJsonAsync(new { Code = 401, Message = "身份验证未通过" });
                    return;
                }
                else
                {
                    await context.Response.WriteAsJsonAsync(new { Code = 403, Message = "您无权限访问此接口" });
                    return;
                }

            }
            await next(context);
        }
    }
}
